package com.lyf.scm.admin.domain.remote.item.facade;


import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageInfo;
import com.lyf.scm.admin.domain.remote.item.ItemCoreRemote;
import com.lyf.scm.admin.domain.remote.item.dto.*;
import com.lyf.scm.common.constants.CommonConstants;
import com.lyf.scm.common.enums.ResponseMsg;
import com.lyf.scm.common.model.SalesPlanSelectDTO;
import com.rome.arch.core.clientobject.Response;
import com.rome.arch.core.exception.RomeException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * description:
 * 外部service调用Facade
 *
 * @author: haodong
 * @data: 2020/7/18 14:06
 */
@Service
@Slf4j
public class ItemCoreFacade {

    @Resource
    private ItemCoreRemote itemCoreRemote;

    /**
     * 根据父品类获取下级品类
     *
     * @param categoryCodeList
     * @return
     */
    public List<SalesPlanSelectDTO> getSubcategoryCode(List<SalesPlanSelectDTO> categoryCodeList) {
        log.info("根据父品类获取下级品类：categoryCodeList：{}", categoryCodeList);
        if (CollectionUtils.isEmpty(categoryCodeList)) {
            return null;
        }
        //对参数集合进行分组，分组后如果size为1，表示全部都只有一个层级，直接返回
        Map<Integer, List<SalesPlanSelectDTO>> listMap = categoryCodeList.stream().collect(Collectors.groupingBy(SalesPlanSelectDTO::getLevel));
        final int reqSize = 1;
        //map长度大于1表示该查询条件携带层级不同的参数，品类有四层level；
        if (listMap.size() > reqSize) {
            // 获取最低级level值
            int subLevel = categoryCodeList.stream().mapToInt(SalesPlanSelectDTO::getLevel).max().getAsInt();
            // 获取level最低的对象集,然后根据高级的条件搜索下级，然后加起来即可
            List<SalesPlanSelectDTO> leafCodeList = categoryCodeList.stream().filter(item -> item.getLevel().equals(subLevel)).collect(Collectors.toList());
            List<String> paramList = new ArrayList<>();
            //如果存在第4级区域->即存在sku
            if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_FOUR))) {
                return this.getParamList(listMap, paramList, CommonConstants.CATEGORY_LEVEL_FOUR, leafCodeList);
            }
            //如果存在第3级区域->品类的叶子节点
            if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_THREE))) {
                return this.getParamList(listMap, paramList, CommonConstants.CATEGORY_LEVEL_THREE, leafCodeList);
            }
            //如果存在第2级区域
            if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_TWO))) {
                return this.getParamList(listMap, paramList, CommonConstants.CATEGORY_LEVEL_TWO, leafCodeList);
            }
        }
        return categoryCodeList;
    }

    /**
     * 处理查询的品类的code集合
     */
    private List<SalesPlanSelectDTO> getParamList(Map<Integer, List<SalesPlanSelectDTO>> listMap, List<String> paramList, Integer level, List<SalesPlanSelectDTO> leafCodeList) {
        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_ONE)) && !CommonConstants.CATEGORY_LEVEL_ONE.equals(level)) {
            listMap.get(CommonConstants.CATEGORY_LEVEL_ONE).forEach(item -> paramList.add(item.getCode()));
        }
        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_TWO)) && !CommonConstants.CATEGORY_LEVEL_TWO.equals(level)) {
            listMap.get(CommonConstants.CATEGORY_LEVEL_TWO).forEach(item -> paramList.add(item.getCode()));
        }
        if (ObjectUtil.isNotEmpty(listMap.get(CommonConstants.CATEGORY_LEVEL_THREE)) && !CommonConstants.CATEGORY_LEVEL_THREE.equals(level)) {
            listMap.get(CommonConstants.CATEGORY_LEVEL_THREE).forEach(item -> paramList.add(item.getCode()));
        }
        Set<SalesPlanSelectDTO> selectDTOS = new HashSet<>();
        if (level.equals(CommonConstants.CATEGORY_LEVEL_FOUR)) {
            Set<SalesPlanSelectDTO> categoryCodes = getCategoryCodes(paramList, selectDTOS, CommonConstants.CATEGORY_LEVEL_THREE);
            leafCodeList.addAll(skuListByCategoryId(categoryCodes));
        } else {
            Set<SalesPlanSelectDTO> categoryCodes = getCategoryCodes(paramList, selectDTOS, level);
            leafCodeList.addAll(categoryCodes);
        }
        return leafCodeList;
    }

    /**
     * 递归获取下级品类的code
     *
     * @param paramList  参数列表
     * @param level      水平
     * @param selectDTOS 选择dto
     * @return {@link Set <Long>}
     */
    private Set<SalesPlanSelectDTO> getCategoryCodes(List<String> paramList, Set<SalesPlanSelectDTO> selectDTOS, Integer level) {
        List<CategoryBaseInfoDTO> response = this.categoryListByCategoryCodes(paramList);
        if (ObjectUtil.isNotEmpty(response)) {
            paramList.clear();
            for (CategoryBaseInfoDTO dto : response) {
                //如果dto.getCategoryDTOList()不为空，说明此品类还有子类
                if (ObjectUtil.isNotEmpty(dto.getCategoryDTOList())) {
                    dto.getCategoryDTOList().forEach(item -> {
                        if (level.equals(item.getLevel())) {
                            selectDTOS.add(this.getSalePlanSelectDTOS(item));
                        } else {
                            paramList.add(item.getCode().toString());
                        }
                    });
                } else {
                    //如果dto.getCategoryDTOList()为空，说明此品类为叶子节点
                    selectDTOS.add(this.getSalePlanSelectDTOS(dto));
                }
            }
            //如果依旧存在不是叶子节点的品类，递归查询
            if (ObjectUtil.isNotEmpty(paramList)) {
                getCategoryCodes(paramList, selectDTOS, level);
            }
        }
        return selectDTOS;
    }

    /**
     * @param dto dto
     * @return {@link SalesPlanSelectDTO}
     */
    private SalesPlanSelectDTO getSalePlanSelectDTOS(CategoryBaseInfoDTO dto) {
        SalesPlanSelectDTO selectDTO = new SalesPlanSelectDTO();
        selectDTO.setId(dto.getId());
        selectDTO.setCode(dto.getCode().toString());
        selectDTO.setName(dto.getName());
        selectDTO.setLevel(dto.getLevel());
        return selectDTO;
    }

    /**
     * 根据叶子节点去获取商品sku ,点击食品加上一个sku，大概需要40秒，慎点
     */
    private List<SalesPlanSelectDTO> skuListByCategoryId(Set<SalesPlanSelectDTO> categoryCodes) {
        List<SalesPlanSelectDTO> strings = new ArrayList<>();
        for (SalesPlanSelectDTO categoryCode : categoryCodes) {
            PageInfo<SkuInfoDTO> response = this.skuListByCategoryId(categoryCode.getId(), 1, 999);
            if (ObjectUtil.isNotEmpty(response.getList())) {
                response.getList().forEach(item -> {
                    SalesPlanSelectDTO selectDTO = new SalesPlanSelectDTO();
                    selectDTO.setCode(item.getSkuCode());
                    selectDTO.setName(item.getName());
                    selectDTO.setLevel(CommonConstants.CATEGORY_LEVEL_FOUR);
                    strings.add(selectDTO);
                });
            }
        }
        return strings;
    }


    /**
     * 根据后台类目父id查询下级节点（查询后台树-鲲鹏）
     *
     * @param parentId
     * @return
     */
    public List<CategoryBaseInfoDTO> getLowerLevelCategoryByParentId(Long parentId) {
        log.info("根据后台类目父id查询下级节点（查询后台树-鲲鹏）：parentId：{}", parentId);
        Response<List<CategoryBaseInfoDTO>> response = itemCoreRemote.getLowerLevelCategoryByParentId(parentId);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 单个根据类目ID查询SKU数据
     *
     * @param categoryId
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageInfo<SkuInfoDTO> skuListByCategoryId(Long categoryId, Integer pageNum, Integer pageSize) {
        log.info("单个根据类目ID查询SKU数据：categoryId,pageNum,pageSize：{}", categoryId + ",", pageNum + ",", pageSize);
        Response<PageInfo<SkuInfoDTO>> response = itemCoreRemote.skuListByCategoryId(categoryId, pageNum, pageSize);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据品类的code查询后台类目信息(包括下一级类目的信息)
     *
     * @param stringList
     * @return
     */
    public List<CategoryBaseInfoDTO> categoryListByCategoryCodes(List<String> stringList) {
        log.info("根据品类的code查询后台类目信息(包括下一级类目的信息)：stringList：{}", stringList);
        Response<List<CategoryBaseInfoDTO>> response = itemCoreRemote.categoryListByCategoryCodes(stringList);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据类目层级查询类目信息
     *
     * @param level
     * @return
     */
    public List<CategoryBaseInfoDTO> getCategoryListByLevel(Integer level) {
        log.info("根据类目层级查询类目信息：level：{}", level);
        Response<List<CategoryBaseInfoDTO>> response = itemCoreRemote.getCategoryListByLevel(level);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据类目编码集合查询类目信息
     *
     * @param secCategoryList
     * @return
     */
    public List<CategoryBaseInfoDTO> listPriCategory(List<String> secCategoryList) {
        log.info("根据类目层级查询类目信息：secCategoryList：{}", secCategoryList);
        Response<List<CategoryBaseInfoDTO>> response = itemCoreRemote.listPriCategoryCode(secCategoryList);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }


    public PageInfo<SkuInfoDTO> getAllCategoryIdBySkuCode(Integer pageNum, Integer pageSize, List<String> skuCodes) {
        log.info("根据商品code集合获取对应品类id集合:pageNum,pageSize,skuCodes:{}", pageNum + ",", pageSize + ",", skuCodes);
        Response<PageInfo<SkuInfoDTO>> response = itemCoreRemote.getAllCategoryIdBySkuCode(pageNum, pageSize, skuCodes);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }


    public List<CategorySimpleDTO> getAllCategoryByCategoryId(List<Integer> ids) {
        log.info("根据品类id集合获取对应品类信息集合，参数：{}", JSON.toJSONString(ids));
        Response<List<CategorySimpleDTO>> response = itemCoreRemote.getAllCategoryByCategoryId(ids);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    public List<SkuInfoDTO> getUtilInfoBySkuCode(List<UnitCodeExtParamDTO> list) {
        log.info("批量通过skuCode和单位名称查询基础单位换算关系，参数：{}", JSON.toJSONString(list));
        Response<PageInfo<SkuInfoDTO>> response = itemCoreRemote.getUtilInfoBySkuCode(list, list.size());
        log.info("批量通过skuCode和单位名称查询基础单位换算关系，响应：{}", JSON.toJSONString(response));
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(response.getCode(), response.getMsg());
        }
        return response.getData().getList();
    }

    public List<SkuUnitExtDTO> getSkuUnitByCodeAndType(List<String> skuCodes, Integer skuUintType) {
        log.info("批量通过skuCodes与skuUintType查询sku单位信息，参数：{}", JSON.toJSONString(skuCodes), skuUintType);
        Response<List<SkuUnitExtDTO>> response = itemCoreRemote.getSkuUnitByCodeAndType(skuCodes, skuUintType);
        log.info("批量通过skuCodes与skuUintType查询sku单位信息，响应：{}", JSON.toJSONString(response));
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(response.getCode(), response.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据品类的code查询后台类目信息(包括下一级类目的信息)
     *
     * @param stringList
     * @return
     */
    public List<CategoryBaseInfoDTO> listByCategoryCodes(List<String> stringList) {
        log.info("根据品类的code查询后台类目信息(包括下一级类目的信息)：stringList：{}", stringList);
        Response<List<CategoryBaseInfoDTO>> response = itemCoreRemote.categoryListByCategoryCodes(stringList);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 根据门店集合查询有进货权限的商品集合
     *
     * @param storeList
     * @param pageNum
     * @param pageSize
     * @return
     */
    public PageInfo<SkuPurchaseAccessDTO> getPurchaseAccessByStores(List<String> storeList, Integer pageNum, Integer pageSize) {
        log.info("根据门店集合查询有进货权限的商品集合,入参{}，{}，{}", storeList, pageNum, pageSize);
        Response<PageInfo<SkuPurchaseAccessDTO>> response = itemCoreRemote.purchaseAccessSkusByStoreCode(storeList, pageNum, pageSize);
        log.info("根据门店集合查询有进货权限的商品集合,返回{}", response);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }

    /**
     * 批量通过categoryId集合查询Sku列表
     *
     * @param pageNum
     * @param categoryId
     * @return {@link PageInfo<SkuInfoDTO>}
     **/
    public PageInfo<SkuInfoDTO> skuListByCategoryId(Integer pageNum, List<Integer> categoryId) {
        log.info("批量通过categoryId集合查询Sku列表：pageNum：{} categoryId：{}", pageNum + ",", categoryId);
        Response<PageInfo<SkuInfoDTO>> response = itemCoreRemote.skusByCategoryId(pageNum, categoryId);
        if (!ResponseMsg.SUCCESS.getCode().equals(response.getCode())) {
            throw new RomeException(ResponseMsg.EXCEPTION_2002.getCode(), ResponseMsg.EXCEPTION_2002.getMsg());
        }
        return response.getData();
    }
}
